package cn.lingyangwl.framework.tool.core.compress;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.io.IOUtils;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.zip.GZIPOutputStream;

/**
 * @author shenguangyang
 */
public class TarUtils {

    /**
     * tar文件批量打包（仅限于文件打包）
     *
     * @param sources 源文件
     * @param target  目标文件
     * @return 返回打包的文件
     */
    public static File packFiles(File target, File[] sources) {
        try (FileOutputStream out = new FileOutputStream(target); TarArchiveOutputStream os = new TarArchiveOutputStream(out)) {
            for (File file : sources) {
                os.putArchiveEntry(new TarArchiveEntry(file, file.getName()));
                IOUtils.copy(Files.newInputStream(file.toPath()), os);
                os.closeArchiveEntry();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return target;
    }

    /**
     * tar文件批量打包（支持文件&文件夹打包）
     *
     * @param destFilePath 目标文件路径
     * @param files        文件
     * @return 结果
     * @throws IOException 异常
     */
    public static String packFilesAndDir(String destFilePath, File... files) throws IOException {
        File destFile = new File(destFilePath);
        if (destFile.exists()) {
            return destFilePath;
        }
        try (FileOutputStream fileOutputStream = new FileOutputStream(destFile);
             BufferedOutputStream bufferedWriter = new BufferedOutputStream(fileOutputStream);
             TarArchiveOutputStream tar = new TarArchiveOutputStream(bufferedWriter)) {

            tar.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);

            for (File file : files) {
                addTarArchiveEntryToTarArchiveOutputStream(file, tar, "");
            }
        }
        return null;
    }

    /**
     * 添加文件到tar输出流中
     *
     * @param file   文件
     * @param tar    tar文件流
     * @param prefix 前缀
     * @throws IOException 异常
     */
    private static void addTarArchiveEntryToTarArchiveOutputStream(File file, TarArchiveOutputStream tar, String prefix) throws IOException {
        TarArchiveEntry entry = new TarArchiveEntry(file, prefix + File.separator + file.getName());

        BasicFileAttributes basicFileAttributes = Files.readAttributes(file.toPath(), BasicFileAttributes.class);
        if (basicFileAttributes.isRegularFile()) {
            entry.setSize(basicFileAttributes.size());
            tar.putArchiveEntry(entry);
            try (FileInputStream fileInputStream = new FileInputStream(file);
                 BufferedInputStream input = new BufferedInputStream(fileInputStream);) {
                IOUtils.copy(input, tar);
            }
            tar.closeArchiveEntry();
        } else {
            tar.putArchiveEntry(entry);
            tar.closeArchiveEntry();
            prefix += File.separator + file.getName();
            File[] files = file.listFiles();
            if (files != null) {
                for (File f : files) {
                    addTarArchiveEntryToTarArchiveOutputStream(f, tar, prefix);
                }
            }
        }
    }

    /**
     * tar文件压缩
     *
     * @param source
     * @return java.io.File
     */
    public static File compress(String outDir, File source) throws IOException {
        File target = new File(outDir + File.separator + source.getName() + ".gz");
        try (FileInputStream in = new FileInputStream(source); GZIPOutputStream out = new GZIPOutputStream(Files.newOutputStream(target.toPath()))) {
            byte[] array = new byte[1024];
            int number = -1;
            while ((number = in.read(array, 0, array.length)) != -1) {
                out.write(array, 0, number);
            }
        }
        return target;
    }

    public static void main(String[] args) throws IOException {
//        File[] sources = new File[]{new File("/usr/local/oas/zhangzhixiang.txt"), new File("/usr/local/oas/dockerFile")};
        packFilesAndDir("/temp/test1.tar", new File("/temp/test1"));
    }
}
